~ chicken-core (chicken-5) /manual/Module (chicken condition)
Trap1[[tags: manual]]2[[toc:]]34== Module (chicken condition)56This module provides various procedures and special forms for raising7and handling exceptions with "condition objects". Condition objects8provide a structured and composable way to encode the kind of9exception that took place, and provide the necessary context.1011CHICKEN's exception handling is based on the12[[http://srfi.schemers.org/srfi-12/srfi-12.html|SRFI-12]] exception13system. This document contains the core of the SRFI-12 spec as well14as CHICKEN implementation specifics.1516There is also a {{srfi-12}} or {{(srfi 12)}} module which only17includes the standard procedures and macros from the SRFI document,18without the CHICKEN extensions. {{(chicken condition)}} offers the19complete set of procedures and macros, both CHICKEN-specific and20standard SRFI-12.212223== CHICKEN implementation2425=== System conditions2627All error-conditions signaled by the system are of kind {{exn}}.28The following composite conditions are additionally defined:2930<table>3132<tr><td> (exn arity) </td><td>3334Signaled when a procedure is called with the wrong number of arguments.3536</td></tr><tr><td> (exn type) </td><td>3738Signaled on type-mismatch errors, for example when an argument of the wrong39type is passed to a built-in procedure.4041</td></tr><tr><td> (exn arithmetic) </td><td>4243Signaled on arithmetic errors, like division by zero.4445</td></tr><tr><td> (exn i/o) </td><td>4647Signaled on input/output errors.4849</td></tr><tr><td> (exn i/o file) </td><td>5051Signaled on file-related errors.5253</td></tr><tr><td> (exn i/o net) </td><td>5455Signaled on network errors.5657</td></tr><tr><td> (exn bounds) </td><td>5859Signaled on errors caused by accessing non-existent elements of a collection.6061</td></tr><tr><td> (exn runtime) </td><td>6263Signaled on low-level runtime-system error-situations.6465</td></tr><tr><td> (exn runtime limit) </td><td>6667Signaled when an internal limit is exceeded (like running out of memory).6869</td></tr><tr><td> (exn match) </td><td>7071Signaled on errors raised by failed matches (see the section on {{match}}).7273</td></tr><tr><td> (exn syntax) </td><td>7475Signaled on syntax errors.7677</td></tr>7879</table>8081=== Notes8283* All error-exceptions (of the kind {{exn}}) are non-continuable.8485* Error-exceptions of the {{exn}} kind have additional {{arguments}} and86{{location}} properties that contain the arguments passed to the87exception-handler and the name of the procedure where the error occurred (if88available).8990* Within the interpreter (csi), a user-interrupt ({{signal/int}}) signals an91exception of the kind {{user-interrupt}}.9293* The procedure {{condition-property-accessor}} accepts an optional third94argument. If the condition does not have a value for the desired property and95if the optional argument is given, no error is signaled and the accessor96returns the third argument.9798* On platforms that support the {{sigprocmask(3)}} POSIX API function,99the signals {{SIGSEGV}}, {{SIGFPE}}, {{SIGBUS}} and {{SIGILL}} will be100caught and trigger an exception instead of aborting the process, if101possible. If the unwinding and handling of the signal raises one of102these signals once again, the process will abort with an error103message.104105* New in CHICKEN 5.4.0: condition objects produced by procedures that106change errno have an {{errno}} property. To access it, use107{{(get-condition-property <the-condition-object> 'exn 'errno)}}.108109=== Additional API110111==== condition-case112113<macro>(condition-case EXPRESSION CLAUSE ...)</macro>114115Evaluates {{EXPRESSION}} and handles any exceptions that are covered by116{{CLAUSE ...}}, where {{CLAUSE}} should be of the following form:117118 CLAUSE = ([VARIABLE] (KIND ...) BODY ...)119120If provided, {{VARIABLE}} will be bound to the signaled exception121object. {{BODY ...}} is executed when the exception is a property-122or composite condition with the kinds given {{KIND ...}} (unevaluated).123If no clause applies, the exception is re-signaled in the same dynamic124context as the {{condition-case}} form.125126<enscript highlight=scheme>127(define (check thunk)128 (condition-case (thunk)129 [(exn file) (print "file error")]130 [(exn) (print "other error")]131 [var () (print "something else")] ) )132133(check (lambda () (open-input-file ""))) ; -> "file error"134(check (lambda () some-unbound-variable)) ; -> "othererror"135(check (lambda () (signal 99))) ; -> "something else"136137(condition-case some-unbound-variable138 ((exn file) (print "ignored")) ) ; -> signals error139</enscript>140141==== get-condition-property142143<procedure>(get-condition-property CONDITION KIND PROPERTY [DEFAULT])</procedure>144145A slightly more convenient condition property accessor, equivalent to146147 ((condition-property-accessor KIND PROPERTY [DEFAULT]) CONDITION)148149==== condition150151<procedure>(condition LST1 LST2 ...)</procedure>152153This is a more convenient constructor for conditions. Each of154{{LST1}}, {{LST2}} etc is a list of the following form:155156 (KIND PROPERTY1 VALUE1 PROPERTY2 VALUE2 ...)157158In other words, the following:159160 (signal (condition '(exn location foo message "hi") '(file bar 1)))161162is equivalent to the SRFI-12 code:163164 (signal (make-composite-condition165 (make-property-condition 'exn 'location 'foo 'message "hi")166 (make-property-condition 'file 'bar 2)))167168169==== condition->list170171<procedure>(condition->list CONDITION)</procedure>172173This procedure converts a condition object into a list holding all the174conditions that are represented by the ''CONDITION'' object. It is175formatted as follows:176177 ((KIND1 PROPERTY1 VALUE1 PROPERTY2 VALUE2 ...) (KIND2 ... ) ... )178179There is no guaranteed order within the list.180181182==== print-error-message183184<procedure>(print-error-message EXN [PORT [HEADER]])</procedure>185186Prints an appropriate error message to {{PORT}} (which defaults to the187value of {{(current-output-port)}} for the object {{EXN}}. {{EXN}} may188be a condition, a string or any other object. The output is prefixed189by the {{HEADER}}, which defaults to {{"Error:"}}.190191192193== SRFI-12 specification194195A Scheme implementation ("the system") raises an exception whenever an196error is to be signaled or whenever the system determines that evaluation197cannot proceed in a manner consistent with the semantics of Scheme. A198program may also explicitly raise an exception.199200Whenever the system raises an exception, it invokes the current exception201handler with a condition object (encapsulating information about the202exception) as its only argument. Any procedure accepting one argument203may serve as an exception handler. When a program explicitly raises an204exception, it may supply any object to the exception handler.205206An exception is either continuable or non-continuable. When the current207exception handler is invoked for a continuable exception, the continuation208uses the handler's result(s) in an exception-specific way to continue.209When an exception handler is invoked for a non-continuable exception,210the continuation raises a non-continuable exception indicating that the211exception handler returned. On CHICKEN, system error exceptions212(of kind {{exn}}) are non-continuable.213214=== Exception Handlers215216==== current-exception-handler217218<parameter>(current-exception-handler [PROCEDURE])</parameter><br>219220Sets or returns the current exception handler, a procedure of one221argument, the exception object.222223==== with-exception-handler224225<procedure>(with-exception-handler handler thunk)</procedure><br>226227Returns the result(s) of invoking ''thunk''. The ''handler'' procedure228is installed as the current exception handler in the dynamic context of229invoking ''thunk''.230231Example:232233<enscript highlight=scheme>234(call-with-current-continuation235 (lambda (k)236 (with-exception-handler (lambda (x) (k '()))237 (lambda () (car '())))))238;=> '()239</enscript>240241Note that the handler procedure must somehow return non-locally out of242the dynamic extent of the {{with-exception-handler}} form, because243returning normally will signal yet another exception and thus result244in non-termination.245246==== handle-exceptions247248<macro>(handle-exceptions var handle-expr expr1 expr2 ...)</macro><br>249250Evaluates the body expressions ''expr1'', ''expr2'', ... in sequence with251an exception handler constructed from ''var'' and ''handle-expr''. Assuming252no exception is raised, the result(s) of the last body expression is(are)253the result(s) of the {{handle-exceptions}} expression.254255The exception handler created by {{handle-exceptions}} restores the dynamic256context (continuation, exception handler, etc.) of the {{handle-exceptions}}257expression, and then evaluates ''handle-expr'' with ''var'' bound to the258value provided to the handler.259260Examples:261262<enscript highlight=scheme>263(handle-exceptions exn264 (begin265 (display "Went wrong")266 (newline))267 (car '()))268; displays "Went wrong"269270(handle-exceptions exn271 (cond272 ((eq? exn 'one) 1)273 (else (abort exn)))274 (case (random 3)275 [(0) 'zero]276 [(1) (abort 'one)]277 [else (abort "Something else")]))278;=> 'zero, 1, or (abort "Something else")279</enscript>280281=== Raising Exceptions282283==== abort284285<procedure>(abort obj)</procedure><br>286287Raises a non-continuable exception represented by ''obj''. The {{abort}}288procedure can be implemented as follows:289290<enscript highlight=scheme>291(define (abort obj)292 ((current-exception-handler) obj)293 (abort (make-property-condition294 'exn295 'message296 "Exception handler returned")))297</enscript>298299The {{abort}} procedure does not ensure that its argument is a condition.300If its argument is a condition, {{abort}} does not ensure that the condition301indicates a non-continuable exception.302303==== signal304305<procedure>(signal obj)</procedure><br>306307Raises a continuable exception represented by ''obj''. The {{signal}} procedure308can be implemented as follows:309310<enscript highlight=scheme>311(define (signal exn)312 ((current-exception-handler) exn))313</enscript>314315The {{signal}} procedure does not ensure that its argument is a condition.316If its argument is a condition, {{signal}} does not ensure that the condition317indicates a continuable exception.318319=== Condition Objects320321==== condition?322323<procedure>(condition? obj)</procedure><br>324325Returns #t if ''obj'' is a condition, otherwise returns #f. If any of326the predicates listed in Section 3.2 of the R5RS is true of ''obj'', then327{{condition?}} is false of ''obj''.328329Rationale: Any Scheme object may be passed to an exception handler. This330would cause ambiguity if conditions were not disjoint from all of Scheme's331standard types.332333==== make-property-condition334335<procedure>(make-property-condition kind-key prop-key value ...)</procedure><br>336337This procedure accepts any even number of arguments after ''kind-key'',338which are regarded as a sequence of alternating ''prop-key'' and ''value''339objects. Each ''prop-key'' is regarded as the name of a property, and340each ''value'' is regarded as the value associated with the ''key'' that341precedes it. Returns a ''kind-key'' condition that associates the given342''prop-key''s with the given ''value''s.343344==== make-composite-condition345346<procedure>(make-composite-condition condition ...)</procedure><br>347348Returns a newly-allocated condition whose components correspond to the349given ''condition''s. A predicate created by {{condition-predicate}} returns350true for the new condition if and only if it returns true for one or more351of its component conditions.352353==== condition-predicate354355<procedure>(condition-predicate kind-key)</procedure><br>356357Returns a predicate that can be called with any object as its argument.358Given a condition that was created by {{make-property-condition}}, the359predicate returns #t if and only if ''kind-key'' is EQV? to the kind key360that was passed to {{make-property-condition}}. Given a composite condition361created with {{make-composite-condition}}, the predicate returns #t if and only362if the predicate returns #t for at least one of its components.363364==== condition-property-accessor365366<procedure>(condition-property-accessor kind-key prop-key [default])</procedure><br>367368Returns a procedure that can be called with any condition that satisfies369{{(condition-predicate ''kind-key'')}}. Given a condition that was created370by {{make-property-condition}} and ''kind-key'', the procedure returns the371value that is associated with ''prop-key''. Given a composite condition372created with {{make-composite-condition}}, the procedure returns the value that373is associated with ''prop-key'' in one of the components that satisfies374{{(condition-predicate ''kind-key'')}}.375376On CHICKEN, this procedure accepts an optional third argument377DEFAULT. If the condition does not have a value for the desired378property and if the optional argument is given, no error is signaled379and the accessor returns the third argument.380381When the system raises an exception, the condition it passes to the382exception handler includes the {{'exn}} kind with the following383properties:384385; message : the error message386; arguments: the arguments passed to the exception handler387; location: the name of the procedure where the error occurred (if available)388389Thus, if ''exn'' is a condition representing a system exception,390then391392<enscript highlight=scheme>393 ((condition-property-accessor 'exn 'message) exn)394</enscript>395396extracts the error message from ''exn''. Example:397398<enscript highlight=scheme>399(handle-exceptions exn400 (begin401 (display "Went wrong: ")402 (display403 ((condition-property-accessor 'exn 'message) exn))404 (newline))405 (car '()))406; displays something like "Went wrong: can't take car of nil"407</enscript>408409=== More Examples410411<enscript highlight=scheme>412(define (try-car v)413 (let ((orig (current-exception-handler)))414 (with-exception-handler415 (lambda (exn)416 (orig (make-composite-condition417 (make-property-condition418 'not-a-pair419 'value420 v)421 exn)))422 (lambda () (car v)))))423424(try-car '(1))425;=> 1426427(handle-exceptions exn428 (if ((condition-predicate 'not-a-pair) exn)429 (begin430 (display "Not a pair: ")431 (display432 ((condition-property-accessor 'not-a-pair 'value) exn))433 (newline))434 (abort exn))435 (try-car 0))436; displays "Not a pair: 0"437438(let* ((cs-key (list 'color-scheme))439 (bg-key (list 'background))440 (color-scheme? (condition-predicate cs-key))441 (color-scheme-background442 (condition-property-accessor cs-key bg-key))443 (condition1 (make-property-condition cs-key bg-key 'green))444 (condition2 (make-property-condition cs-key bg-key 'blue))445 (condition3 (make-composite-condition condition1 condition2)))446 (and (color-scheme? condition1)447 (color-scheme? condition2)448 (color-scheme? condition3)449 (color-scheme-background condition3)))450; => 'green or 'blue451</enscript>452453----454Previous: [[Module (chicken blob)]]455456Next: [[Module (chicken continuation)]]